package com.wimcorp.magic.phase;

import java.rmi.RemoteException;

import com.wimcorp.magic.abilities.Ability;
import com.wimcorp.magic.exception.CostException;
import com.wimcorp.magic.players.Player;
import com.wimcorp.magic.stack.Stack;
import com.wimcorp.magic.userinterface.UserInterface;

public abstract class Phase {

	private Player activePlayer;

	public Phase(Player activePlayer) {
		this.activePlayer = activePlayer;
	}

	public abstract void execute();

	protected void activateAbilities() {
		executeActivateAbilities();
		setActivePlayer(getActivePlayer().getOpponent());
		executeActivateAbilities();
		setActivePlayer(getActivePlayer().getOpponent());

	}

	private void executeActivateAbilities() {
		if (getActivePlayer().getSummoningPlaines().getCastableAbilitiesOnBatleField() > 0) {
			try {
				boolean cast = getActivePlayerUserInterface().selectBoolean("Would you like to activate an ability?");
				while (cast) {
					activateAbility();
					cast = getActivePlayerUserInterface().selectBoolean("Would you like to activate another ability?");
				}
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		} else {
			messagePlayer("Skipping cast abilities phase - You have no active abilities. ");
		}
	}

	public void activateAbility() throws RemoteException {
		long abilityId = getActivePlayerUserInterface().castAbility();
		if (abilityId != -1) {
			Ability ability = getActivePlayer().getSummoningPlaines().getAbility(abilityId);
			getActivePlayer().cast(ability);
			messagePlayer(String.format("You activated %s. ", ability.getCastDescription()));
			messageOpponent(String.format("Opponent %s activated %s", getActivePlayer().getOpponent().getName(),
					ability.getCastDescription()));
			//if (getActivePlayer().getOpponent().getSummoningPlaines().getCastableAbilitiesOnBatleField() > 0) {
				boolean counterAbility = getActivePlayer().getOpponent().getUserInterface()
						.selectBoolean(String.format("Would you like to counter %s?", ability.getCastDescription()));
				if (counterAbility) {
					messagePlayer(String.format("Opponent wants to counter %s. ", ability.getCastDescription()));
					setActivePlayer(getActivePlayer().getOpponent());
					counterAbility();
					setActivePlayer(getActivePlayer().getOpponent());
				}
			//} else {
			//	messagePlayer(String.format("Opponent does not counter %s. ", ability.getCastDescription()));
			//	messageOpponent("Skipping counter abilities phase - You have no active abilities. ");
			//}
			// resolve stack
			getStack().resolve();
		} else {
			messagePlayer(String.format("Ability with %s not found.", abilityId));
		}
	}

	private void counterAbility() throws RemoteException {
		try {
			long abilityId = -1;
			do {
				abilityId = getActivePlayer().getUserInterface().castAbility();
				if (abilityId != -1) {
					Ability ability = getActivePlayer().getSummoningPlaines().getAbility(abilityId);

					getActivePlayer().cast(ability);

					messagePlayer(String.format("You activated %s. ", ability.getCastDescription()));
					if (ability.isInputRequired()) {
						ability.configureTarget();
						messageOpponent(String.format("Opponent %s activated %s with target %s", getActivePlayer()
								.getName(), ability.getCastDescription(), ability.getAbilityTarget().getName()));
					} else {
						messageOpponent(String.format("Opponent %s activated %s", getActivePlayer().getOpponent()
								.getName(), ability.getCastDescription()));
					}

					boolean counterAbility = getActivePlayer().getOpponent().getUserInterface()
							.selectBoolean(String.format("Would you like to counter %s?", ability.getCastDescription()));
					if (counterAbility) {
						setActivePlayer(getActivePlayer().getOpponent());
						counterAbility();
						setActivePlayer(getActivePlayer().getOpponent());
					}
				} else {
					messagePlayer(String.format("Ability with %s not found.", abilityId));
				}
			} while (abilityId != -1);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}

	public Player getActivePlayer() {
		return activePlayer;
	}

	public UserInterface getActivePlayerUserInterface() {
		return activePlayer.getUserInterface();
	}

	public void setActivePlayer(Player activePlayer) {
		this.activePlayer = activePlayer;
	}

	public Stack getStack() {
		return activePlayer.getStack();
	}

	public void messagePlayer(String message) {
		message(getActivePlayer(), message);
	}

	public void messageOpponent(String message) {
		message(getActivePlayer().getOpponent(), message);
	}

	private void message(Player player, String message) {
		try {
			player.getUserInterface().message(message);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}

}
